package routers

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"shqsoft.cn/pasnj/base"
	"shqsoft.cn/pasnj/entity"
	"shqsoft.cn/pasnj/xmla"

	"github.com/labstack/echo"
)

//HomeRequest 首页请求
type HomeRequest struct {
	StartDate  string `json:"startDate"`
	EndDate    string `json:"endDate"`
	HiddenNil  bool   `json:"hiddenNil"`
	Currency   string `json:"currency"`
	UniqueName string `json:"uniqueName"`
	IndexID    string `json:"indexID"`
	Unit       int    `json:"unit"`
	IndexWhere string `json:"indexWhere"`
}

//HomeResponseAll 首页相应
type HomeResponseAll struct {
	Title1    string         `json:"title1"`
	List1     []HomeResponse `json:"list1"`
	Title2    string         `json:"title2"`
	List2     []HomeResponse `json:"list2"`
	IndexID   string         `json:"indexID"`
	NextUName string         `json:"nextUName"`
}

//HomeResponse2 首页相应
type HomeResponse2 struct {
	Title2 string         `json:"title2"`
	List2  []HomeResponse `json:"list2"`
}

//HomeResponse 首页相应
type HomeResponse struct {
	ItemID   string   `json:"itemID"`
	ItemName string   `json:"itemName"`
	ACBL     *float64 `json:"ACBL"`
	BSR      *float64 `json:"BSR"`
	BSY      *float64 `json:"BSY"`
	BSN      *float64 `json:"BSN"`
}

//HomeRequestAllRouter 首页请求路由All
func HomeRequestAllRouter(c echo.Context) (err error) {
	var req HomeRequest
	jsonStr := c.FormValue("HomeRequest")
	if jsonStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "HomeRequest不能为空！")
	}
	err = json.Unmarshal([]byte(jsonStr), &req)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	data1, data2, nextUName, err := execRequest(&req, "All")
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	t1, t2, err := getTitles(req.UniqueName, req.IndexID)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	indexID := ""
	if req.UniqueName != "[员工].[员工名称].[All]" {
		indexID = req.IndexID
	}
	allData := HomeResponseAll{
		List1:     data1,
		List2:     data2,
		Title1:    t1,
		Title2:    t2,
		IndexID:   indexID,
		NextUName: nextUName,
	}
	return c.JSON(http.StatusOK, allData)
}

//HomeRequest2Router 首页请求路由2
func HomeRequest2Router(c echo.Context) (err error) {
	var req HomeRequest
	jsonStr := c.FormValue("HomeRequest")
	if jsonStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "HomeRequest不能为空！")
	}
	err = json.Unmarshal([]byte(jsonStr), &req)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	_, list2, _, err := execRequest(&req, "2")
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	_, t2, err := getTitles(req.UniqueName, req.IndexID)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	data2 := HomeResponse2{
		List2:  list2,
		Title2: t2,
	}
	return c.JSON(http.StatusOK, data2)
}

func getTitles(uName string, indexID string) (title1 string, title2 string, err error) {
	var ind entity.PASIndex
	if err = base.DB.First(&ind, indexID).Error; err != nil {
		return
	}
	indexName := ind.INNM
	if ind.INID > 1000 {
		indexName = strings.Replace(ind.INNM, "其中：", "", -1)
	}
	if uName == "[员工].[员工名称].[All]" {
		title1 = "分行主要业绩指标一览表"
		title2 = fmt.Sprintf("部门%s业绩指标一览表", indexName)
	} else if strings.Index(uName, "[员工].[管辖部门]") == 0 || strings.Index(uName, "[员工].[所属部门]") == 0 {
		i1 := strings.LastIndex(uName, "[") + 1
		i2 := len(uName) - 1
		key := uName[i1:i2]
		var org entity.Organization
		if err = base.DB.First(&org, key).Error; err != nil {
			return
		}
		title1 = fmt.Sprintf("%s业绩指标一览表", org.Name)
		title2 = fmt.Sprintf("%s%s业绩指标一览表", org.Name, indexName)
	} else {
		i1 := strings.LastIndex(uName, "[") + 1
		i2 := len(uName) - 1
		key := uName[i1:i2]
		var user entity.User
		if err = base.DB.First(&user, key).Error; err != nil {
			return
		}
		title1 = fmt.Sprintf("%s业绩指标一览表", user.Name)
		title2 = fmt.Sprintf("%s客户%s业绩指标一览表", user.Name, indexName)
	}
	return
}

func getLevel(uName string, indexID int, txid int) (level string, nextUName string, err error) {
	if uName == "[员工].[员工名称].[All]" {
		level = "[员工].[管辖部门].[管辖部门]"
		nextUName = "[员工].[管辖部门]"
	} else if strings.Index(uName, "[员工].[管辖部门]") == 0 {
		start := strings.LastIndex(uName, "[") + 1
		end := strings.LastIndex(uName, "]")
		names := []byte(uName)
		orgID := string(names[start:end])
		sql := "select count(ID) from T_Organization where ParentOrganID=?"
		row := base.DB.Raw(sql, orgID).Row()
		var count int
		err := row.Scan(&count)
		if err != nil {
			return "", "", err
		}
		if count > 0 {
			level = "[员工].[部门-员工].[所属部门]"
			nextUName = "[员工].[所属部门]"
		} else {
			level = "[员工].[部门-员工].[员工名称]"
			nextUName = "[员工].[员工名称]"
		}
	} else if strings.Index(uName, "[员工].[所属部门]") == 0 {
		level = "[员工].[部门-员工].[员工名称]"
		nextUName = "[员工].[员工名称]"
	} else if strings.Index(uName, "[员工].[员工名称]") == 0 {
		dgzbIds := []int{5328, 5329, 5334, 5337, 5338, 5340}
		lszbIds := []int{5330, 5331, 5332, 5335, 5339, 5341, 5343, 5344, 53411, 53412, 53413, 53414, 53415, 5345}
		if base.IsInSliceForInt(dgzbIds, indexID) {
			level = "[对公客户].[客户名称].[客户名称]"
		} else if base.IsInSliceForInt(lszbIds, indexID) {
			level = "[零售客户].[零售客户].[零售客户]"
		} else {
			err = errors.New("总存款和总贷款不能查询客户")
		}
	} else {
		err = fmt.Errorf("无效的uniqueName表达式:%s", uName)
	}
	return
}

func execRequest(req *HomeRequest, part string) (data1 []HomeResponse, data2 []HomeResponse, nextUName string, err error) {
	var mdx string
	port := new(xmla.DefaultXMLAPort)
	port.SetUrl(base.Context.Xmla.Url)
	p := &xmla.XMLAExecuteProperties{
		DataSourceInfo: base.Context.Xmla.DataSourceInfo,
		Catalog:        base.Context.Xmla.Catalog,
		Format:         "Multidimensional",
		Content:        "Data",
		AxisFormat:     "TupleFormat",
	}
	var firstIndexID string
	if part == "All" || part == "1" {
		mdx, err = getAllIndexByUniqueName(req.StartDate, req.EndDate, req.Currency, req.HiddenNil, req.UniqueName, req.IndexWhere)
		if err != nil {
			return nil, nil, "", err
		}
		cData, err := port.Execute(&mdx, p)
		if err != nil {
			return nil, nil, "", err
		}
		if cData.RowAxis == nil {
			return nil, nil, "", err
		}
		rowAxis := *cData.RowAxis
		rowLen := len(rowAxis)
		if rowLen <= 0 {
			return nil, nil, "", nil
		}
		var resps1 []HomeResponse
		resps1 = make([]HomeResponse, rowLen, rowLen)
		first := 1
		for i, rowTuples := range rowAxis {
			j := i
			k := len(rowTuples) - 1
			resps1[j].ItemName = rowTuples[k].Caption
			resps1[j].ItemID = base.ToString(cData.CellData[i][0])
			resps1[j].ACBL = base.ToFloat64(cData.CellData[i][1])
			resps1[j].BSR = base.ToFloat64(cData.CellData[i][2])
			resps1[j].BSY = base.ToFloat64(cData.CellData[i][3])
			resps1[j].BSN = base.ToFloat64(cData.CellData[i][4])
		}
		firstIndexID = resps1[first].ItemID
		data1 = resps1
	}
	if part == "All" || part == "2" {
		if req.IndexID == "" {
			req.IndexID = firstIndexID
		}
		indID, err := strconv.Atoi(req.IndexID)
		if err != nil {
			return nil, nil, "", err
		}
		mdx, nextUName, err = getIndexByMembers(req.StartDate, req.EndDate, req.Currency, req.HiddenNil, req.UniqueName, indID)
		if err != nil {
			return nil, nil, "", err
		}
		cData, err := port.Execute(&mdx, p)
		if err != nil {
			return nil, nil, "", err
		}
		rowAxis := *cData.RowAxis
		rowLen := len(rowAxis)
		resps2 := make([]HomeResponse, rowLen, rowLen)
		for i, rowTuples := range rowAxis {
			k := len(rowTuples) - 1
			resps2[i].ItemName = rowTuples[k].Caption
			resps2[i].ItemID = base.ToString(cData.CellData[i][0])
			resps2[i].ACBL = base.ToFloat64(cData.CellData[i][1])
			resps2[i].BSR = base.ToFloat64(cData.CellData[i][2])
			resps2[i].BSY = base.ToFloat64(cData.CellData[i][3])
			resps2[i].BSN = base.ToFloat64(cData.CellData[i][4])
		}
		data2 = resps2
	}
	return
}

//getAllIndexByUniqueName 获取指定成员获取所有指标MDX
func getAllIndexByUniqueName(sdate string, edate string, cyno string, hiddenNil bool, uname string, indexWhere string) (string, error) {
	var buff bytes.Buffer
	buff.WriteString("WITH MEMBER [Measures].[DAYS] AS COUNT({[日期].[时间].&[")
	buff.WriteString(sdate)
	buff.WriteString("]:[日期].[时间].CURRENTMEMBER})\r\n")
	buff.WriteString("MEMBER [Measures].[ID] AS [考核指标2018].[指标名称].CURRENTMEMBER.MEMBER_KEY\r\n")
	buff.WriteString("MEMBER [Measures].[ACBL] AS CASE [考核指标2018].[指标名称].CURRENTMEMBER.MEMBERVALUE ")
	var indexs []entity.PASIndex
	if err := base.DB.Find(&indexs).Error; err != nil {
		return "", err
	}
	for _, index := range indexs {
		isnull := false
		if cyno == "14" && !index.HASW {
			isnull = true
		}
		buff.WriteString("WHEN ")
		buff.WriteString(strconv.Itoa(index.INID))
		buff.WriteString(" THEN ")
		createIndexMdx(&buff, sdate, index.AGG, index.TPMDX, isnull)
		buff.WriteString("\r\n")
	}
	buff.WriteString("END\r\n")
	buff.WriteString("MEMBER [Measures].[BASE] AS CASE [考核指标2018].[指标名称].CURRENTMEMBER.MEMBERVALUE\r\n")
	for _, index := range indexs {
		isnull := false
		if cyno == "14" && !index.HASW {
			isnull = true
		}
		buff.WriteString("WHEN ")
		buff.WriteString(strconv.Itoa(index.INID))
		buff.WriteString(" THEN ")
		if index.BSMDX == "" || isnull {
			buff.WriteString("NULL")
		} else {
			buff.WriteString(strings.Replace(index.BSMDX, "#SDATE", sdate, -1))
		}
		buff.WriteString("\r\n")
	}
	buff.WriteString("END\r\n")
	buff.WriteString("MEMBER [Measures].[BSR] AS CASE [考核指标2018].[指标名称].CURRENTMEMBER.MEMBERVALUE\r\n")
	for _, index := range indexs {
		isnull := false
		if cyno == "14" && !index.HASW {
			isnull = true
		}
		buff.WriteString("WHEN ")
		buff.WriteString(strconv.Itoa(index.INID))
		if index.AGG == "lastdate" && !isnull && index.INID != 295 && index.INID != 741 {
			buff.WriteString(" THEN [Measures].[ACBL]-([日期].[时间].CURRENTMEMBER.PREVMEMBER,[Measures].[BASE])")
		} else {
			buff.WriteString(" THEN NULL")
		}
		buff.WriteString("\r\n")
	}
	buff.WriteString("END\r\n")

	buff.WriteString("MEMBER [Measures].[BSY] AS CASE [考核指标2018].[指标名称].CURRENTMEMBER.MEMBERVALUE\r\n")
	for _, index := range indexs {
		isnull := false
		if cyno == "14" && !index.HASW {
			isnull = true
		}
		buff.WriteString("WHEN ")
		buff.WriteString(strconv.Itoa(index.INID))
		if (index.AGG == "lastdate" || index.AGG == "avg") && !isnull {
			if index.AGG == "lastdate" {
				buff.WriteString(" THEN [Measures].[ACBL]-(ANCESTOR([日期].[时间].CurrentMember, [日期].[时间].[月]).PREVMEMBER.lastchild,[Measures].[BASE])")
			} else {
				buff.WriteString(" THEN [Measures].[ACBL]-(ANCESTOR([日期].[时间].CurrentMember, [日期].[时间].[月]).PREVMEMBER,[Measures].[BASE])")
			}
		} else if index.AGG == "count" && !isnull {
			buff.WriteString(" THEN SUM(PERIODSTODATE([日期].[时间].[月],[日期].[时间].CurrentMember),[Measures].[BASE])")
		} else if index.AGG == "sum" || isnull {
			buff.WriteString(" THEN NULL")
		}
		buff.WriteString("\r\n")
	}
	buff.WriteString("END\r\n")
	// if strings.Index(uname, "[员工].[管辖部门]") == 0 || strings.Index(uname, "[员工].[所属部门]") == 0 || strings.Index(uname, "[员工].[员工名称]") == 0 {
	// 	tzjs = true
	// }
	buff.WriteString("MEMBER [Measures].[BSN] AS CASE [考核指标2018].[指标名称].CURRENTMEMBER.MEMBERVALUE\r\n")
	for _, index := range indexs {
		isnull := false
		if cyno == "14" && !index.HASW {
			isnull = true
		}
		buff.WriteString("WHEN ")
		buff.WriteString(strconv.Itoa(index.INID))
		if !isnull {
			if index.AGG == "count" {
				buff.WriteString(" THEN SUM(PERIODSTODATE([日期].[时间].[月],[日期].[时间].CurrentMember),[Measures].[BASE])")
			} else if index.AGG == "sum" || index.INID == 295 || index.INID == 741 {
				buff.WriteString(" THEN [Measures].[ACBL]")
			} else {
				buff.WriteString(" THEN [Measures].[ACBL]-(ANCESTOR([日期].[时间].CurrentMember, [日期].[时间].[年]).PREVMEMBER,[Measures].[BASE])")
			}
		} else {
			buff.WriteString(" THEN NULL")
		}
		buff.WriteString("\r\n")
	}
	buff.WriteString("END\r\n")
	buff.WriteString("SELECT {[Measures].[ID],[Measures].[ACBL],[Measures].[BSR],[Measures].[BSY],[Measures].[BSN]} ON 0,")
	if hiddenNil {
		buff.WriteString("NONEMPTY([考核指标2018].[指标名称].[指标名称].MEMBERS,{[Measures].[ACBL],[Measures].[BSN]}) ON 1")
	} else {
		buff.WriteString("[考核指标2018].[指标名称].[指标名称].MEMBERS  ON 1")
	}
	buff.WriteString("\r\n")
	buff.WriteString("FROM [Yybankdw] WHERE ([日期].[日期].&[")
	buff.WriteString(edate)
	buff.WriteString("],")
	if cyno == "01" {
		buff.WriteString("[币种].[币种].&[01],")
	} else if cyno == "14" {
		buff.WriteString("{[币种].[币种].[币种].members-[币种].[币种].&[01]},")
	}
	buff.WriteString(uname)
	// buff.WriteString(",[考核指标2018].[指标条线].&[1]")
	buff.WriteString(indexWhere)

	buff.WriteString(")")
	println(buff.String())
	return buff.String(), nil
}
func createIndexMdx(buff *bytes.Buffer, sdate string, agg string, mdx string, isnull bool) {
	if mdx == "" || isnull {
		buff.WriteString(" NULL ")
		return
	}
	mdx = strings.Replace(mdx, "#SDATE", sdate, -1)
	if agg == "avg" || agg == "sum" {
		buff.WriteString("SUM({[日期].[时间].&[")
		buff.WriteString(sdate)
		buff.WriteString("]:[日期].[时间].CURRENTMEMBER},")
		buff.WriteString(mdx)
		if agg == "sum" {
			buff.WriteString(")")
		} else {
			buff.WriteString(")/[Measures].[DAYS]")
		}
	} else if agg == "count" {
		buff.WriteString("SUM({[日期].[时间].&[20090101]:[日期].[时间].CURRENTMEMBER},")
		buff.WriteString(mdx)
		buff.WriteString(")")
	} else {
		buff.WriteString(mdx)
	}
}

//getIndexByMembers 获取成员集合的指定指标MDX
func getIndexByMembers(sdate string, edate string, cyno string, hiddenNil bool, uname string, index int) (string, string, error) {
	var buff bytes.Buffer
	buff.WriteString("WITH MEMBER [Measures].[DAYS] AS COUNT({[日期].[时间].&[")
	buff.WriteString(sdate)
	buff.WriteString("]:[日期].[时间].CURRENTMEMBER})\r\n")
	buff.WriteString("MEMBER [Measures].[ID] AS ")
	var pIndex entity.PASIndex
	if err := base.DB.First(&pIndex, index).Error; err != nil {
		return "", "", err
	}
	level, nextUName, err := getLevel(uname, index, pIndex.TXID)
	if err != nil {
		return "", "", err
	}
	levs := strings.Split(level, ".")
	hie := strings.Join(levs[:2], ".")
	buff.WriteString(hie)
	buff.WriteString(".CURRENTMEMBER.MEMBER_KEY\r\n")
	isnull := false
	if cyno == "14" && !pIndex.HASW {
		isnull = true
	}
	buff.WriteString("MEMBER [Measures].[ACBL] AS ")
	createIndexMdx(&buff, sdate, pIndex.AGG, pIndex.TPMDX, isnull)
	buff.WriteString("\r\n")
	buff.WriteString("MEMBER [Measures].[BASE] AS ")
	buff.WriteString(strings.Replace(pIndex.BSMDX, "#SDATE", sdate, -1))
	buff.WriteString("\r\n")
	buff.WriteString("MEMBER [Measures].[BSR] AS ")
	if pIndex.AGG == "lastdate" && !isnull && pIndex.INID != 295 && pIndex.INID != 741 {
		buff.WriteString("[Measures].[ACBL]-([日期].[时间].CURRENTMEMBER.PREVMEMBER,[Measures].[BASE])")
	} else if pIndex.AGG == "sum" {
		buff.WriteString("[Measures].[ACBL]")
	} else {
		buff.WriteString("null")
	}
	buff.WriteString("\r\n")
	buff.WriteString("MEMBER [Measures].[BSY] AS ")
	if pIndex.AGG == "lastdate" || pIndex.AGG == "avg" && !isnull {
		if pIndex.AGG == "lastdate" {
			buff.WriteString("[Measures].[ACBL]-(ANCESTOR([日期].[时间].CurrentMember, [日期].[时间].[月]).PREVMEMBER.lastchild,[Measures].[BASE])")
		} else {
			buff.WriteString("[Measures].[ACBL]-(ANCESTOR([日期].[时间].CurrentMember, [日期].[时间].[月]).PREVMEMBER,[Measures].[BASE])")
		}
	} else if pIndex.AGG == "count" && !isnull {
		buff.WriteString("SUM(PERIODSTODATE([日期].[时间].[月],[日期].[时间].CurrentMember),[Measures].[BASE])")
	} else if pIndex.AGG == "sum" {
		buff.WriteString("[Measures].[ACBL]")
	} else {
		buff.WriteString("null")
	}
	buff.WriteString("\r\n")
	// tzjs := false
	// if uname == "[员工].[员工名称].[All]" || strings.Index(uname, "[员工].[管辖部门]") == 0 || strings.Index(uname, "[员工].[所属部门]") == 0 {
	// 	tzjs = true
	// }
	buff.WriteString("MEMBER [Measures].[BSN] AS ")
	if isnull {
		buff.WriteString("null")
	} else if pIndex.AGG == "count" {
		buff.WriteString("SUM(PERIODSTODATE([日期].[时间].[年],[日期].[时间].CurrentMember),[Measures].[BASE])")
	} else if pIndex.AGG == "sum" || pIndex.INID == 295 || pIndex.INID == 741 {
		buff.WriteString("[Measures].[ACBL]")
	} else {
		buff.WriteString("[Measures].[ACBL]-(ANCESTOR([日期].[时间].CurrentMember, [日期].[时间].[年]).PREVMEMBER,[Measures].[BASE])")
	}
	buff.WriteString("\r\n")
	buff.WriteString("SELECT {[Measures].[ID],[Measures].[ACBL],[Measures].[BSR],[Measures].[BSY],[Measures].[BSN]} ON 0,")
	buff.WriteString("\r\n")
	buff.WriteString("NONEMPTY(")
	buff.WriteString(level)
	buff.WriteString(".MEMBERS,{[Measures].[ACBL],[Measures].[BSN]}) ON 1")
	buff.WriteString("\r\n")
	buff.WriteString("FROM [Yybankdw] WHERE ([日期].[日期].&[")
	buff.WriteString(edate)
	buff.WriteString("],")
	if cyno == "01" {
		buff.WriteString("[币种].[币种].&[01],")
	} else if cyno == "14" {
		buff.WriteString("{[币种].[币种].[币种].members-[币种].[币种].&[01]},")
	}
	buff.WriteString(uname)

	buff.WriteString(")")
	return buff.String(), nextUName, nil
}
